This page last changed on Oct 20, 2006 by cholmes.
Introduction
An output format is what form Geoserver returns requested data. By default, a getFeature request returns the feature(s) in GML2. Another output type can be Shapefile.
To specify what output format you want returned by Geoserver, just append the outputformat=mytype argument to the URL.
http://localhost:8080/geoserver/wfs?
request=getfeature&
service=wfs&
version=1.0.0&
typename=states&
outputformat=SHAPE-ZIP
Here are some output formats that come with Geoserver:
![](./icons/emoticons/forbidden.gif) | Note
This is an advanced tutorial. It tells you where to put your files and what interfaces you will have to implement. It assumes you are moderately experienced with java and have used the java.IO.OutputStream class. |
Overview
There are two files you must add, and one you must modify.
- Create MyFormatFeatureResponseDelegate.java
- Create MyFormatFeatureResponseDelegateFactory.java
- Modify org.vfny.geoserver.wfs.FeatureResponseDelegateProducerSpi
STEP 1: Create MyFormatFeatureResponseDelegate.java
In the package org.vfny.geoserver.wfs.responses, create your class MyFormatFeatureResponseDelegate.java
It must implement the FeatureResponseDelegate interface:
public interface FeatureResponseDelegate
{
boolean canProduce(String outputFormat);
void prepare(String outputFormat, GetFeatureResults results)
throws IOException;
String getContentType(GeoServer gs);
String getContentEncoding();
void encode(OutputStream output) throws ServiceException, IOException;
}
Also, create a global variable called results that is a GetFeatureResults object.
private GetFeatureResults results;
STEP 1.1: canProduce(String outputFormat)
This is a very simple method. It basically looks at the output format string passed in and checks to see if this class can handle it. Here is an example of how the GML FeatureResponseDelegate handles it:
public boolean canProduce(String outputFormat)
{
return "GML2".equalsIgnoreCase(outputFormat)
|| "GML2-GZIP".equalsIgnoreCase(outputFormat);
}
STEP 1.2: prepare(String outputFormat, GetFeatureResults results)
The prepare method is called before any output is processed. It is used to set up Geoserver for the selected output format. In here you want to do all your initial setup in order to throw any errors early, before you start pulling out the data. You also save the results passed in from the parameters. This method doesn't have to do anything fancy, and your output format might not have anything it can prepare. It is just here to give the programmer a chance to detect errors early on, and possibly handle them, and to hold onto the results from the query. So if you want, you can leave it blank except for the one line:
Here is an example from the ShapeFeatureResponseDelegate class:
public void prepare(String outputFormat, GetFeatureResults results) throws IOException
{
this.results = results;
if (results == null) {
throw new IllegalStateException(
"It seems prepare() has not succeed. <results> is null");
}
tempDir = System.getProperty("java.io.tmpdir");
if (tempDir == null) {
throw new NullPointerException("<tempDir> is null. " +
"There is a problem with the java.io.tempdir directory.");
}
}
STEP 1.3: getContentType(GeoServer gs)
TODO: Fill in this step.
For now, just have your method return this:
STEP 1.4: getContentEncoding()
This method will return a string that describes how the content has been encoded, if it has been encoded at all. If it has not been encoded, have it return null.
Here is an example from the ShapeFeatureResponseDelegate class:
public String getContentEncoding() {
return "zip";
}
STEP 1.5: encode(OutputStream output)
Here is where the actual output occurs. All of the data must be written out to the OutputStream. I can't go into too much detail as what you have to do here, because it depends on your output format. But take a look at the Shapefile and GML output formats.
![](./icons/emoticons/warning.gif) | Note: Use close()
It is important to note that if you open any other output streams, not the one passed in but if you make another one, that you close them. |
STEP 2: Create MyFormatFeatureResponseDelegateFactory.java
In the package org.vfny.geoserver.wfs.responses, create your class MyFormatFeatureResponseDelegateProducer.java
Your class must implement FeatureResponseDelegateProducerSpi:
public interface FeatureResponseDelegateProducerSpi extends Factory
{
String getName();
Set getSupportedFormats();
boolean isAvailable();
boolean canProduce(String format);
FeatureResponseDelegate createFeatureDelegateProducer(String format)
throws IllegalArgumentException;
Also, create a global static variable that is a java.util.HashSet.
In it, store the possible types that this factory can handle. Here is an example from GML2FeatureResponseDelegateFactory:
static HashSet supportedFormats = new HashSet();
static{
supportedFormats.add("GML2");
supportedFormats.add("GML2-GZIP");
}
STEP 2.1: getName()
This method returns a descriptive name for the factory instance. For example in ShapefileFeatureResponseDelegateFactory:
public String getName() {
return "Shapefile Output (compressed in a zip file)";
}
STEP 2.2: getSupportedFormats()
This method returns all the supported output types. All it has to look like is this:
public Set getSupportedFormats()
{
return supportedFormats;
}
Just return the HashSet you created back in step 2.0.
STEP 2.3: isAvailable()
This method determines whether this factory is able to produce producer instances.
Both ShapefileFeatureResponseDelegateFactory and GML2FeatureResponseDelegateFactory just return true.
STEP 2.4: canProduce(String format)
Returns true if this factory can create the specified output format.
It is the same as the canProduce() method from your MyFormatFeatureResponseDelegate class
STEP 2.5: createFeatureDelegateProducer(String format)
This method will create a new MyFormatFeatureResponseDelegate. It should check to see if the format can be created, and then create the object.
Here is what the method looks like in GML2FeatureResponseDelegateFactory:
public FeatureResponseDelegate createFeatureDelegateProducer(String format) throws IllegalArgumentException
{
if (canProduce(format))
return new GML2FeatureResponseDelegate();
throw new IllegalArgumentException("cannot produce "+format);
}
STEP 3: Modify FeatureResponseDelegateProducerSpi
Navigate to your Geoserver source directory, then to META-INF\services.
Open up the file org.vfny.geoserver.wfs.FeatureResponseDelegateProducerSpi
Add the line:
org.vfny.geoserver.wfs.responses.MyFormatFeatureResponseDelegateFactory
Test It Out
Try it out by using the below URL, but change it to point to your running Geoserver instance and to use your new output format.
http://localhost:8080/geoserver/wfs?
request=getfeature&
service=wfs&
version=1.0.0&
typename=states&
outputformat=SHAPE-ZIP
The outputformat string should be the same as the strings in the canProduce(String format) methods you created.
|